package com.bbjob.service.impl;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.bbjob.client.dataentity.ResultForDeliveryClientLoginLog;
import com.bbjob.client.dataentity.ResultForDeliveryClientLoginLogs;
import com.bbjob.dto.Result;
import com.bbjob.mapper.DeliveryClientLoginLogMapper;
import com.bbjob.mapper.DeliveryCommitLogMapper;
import com.bbjob.mapper.DeliveryExamInfoMapper;
import com.bbjob.mapper.DeliveryExamineeInfoMapper;
import com.bbjob.mapper.DeliveryQuestionBankMapper;
import com.bbjob.mapper.DeliverySocketMsgLogMapper;
import com.bbjob.model.DeliveryClientLoginLog;
import com.bbjob.model.DeliveryCommitLog;
import com.bbjob.model.DeliveryExamInfo;
import com.bbjob.model.DeliveryExamineeInfo;
import com.bbjob.model.DeliveryQuestionBank;
import com.bbjob.model.DeliverySocketMsgLog;
import com.bbjob.query.MachineInfo;
import com.bbjob.service.IClientService;
import com.bbjob.service.ISystemService;
import com.bbjob.toolutil.HttpClientUtil;
import com.bbjob.toolutil.Tool;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;

@Service
public class ClientServiceImpl implements IClientService {
	
	@Value("${sys.uniquecode}")
	private String uniquecode;
	@Value("${examol.center.url}")
	private String centerUrl;
	@Value("${examol.center.client.login}")
	private String centerClientLoginUrl;
	
	@Resource
	private DeliveryExamineeInfoMapper deliveryExamineeInfoMapper;

	@Resource
	private DeliveryExamInfoMapper deliveryExamInfoMapper;
	
	@Resource
	private DeliveryQuestionBankMapper deliveryQuestionBankMapper;
	
	@Resource
	private DeliveryClientLoginLogMapper deliveryClientLoginLogMapper;
	
	@Resource
	private DeliveryCommitLogMapper deliveryCommitLogMapper;
	
	@Resource
	private DeliverySocketMsgLogMapper deliverySocketMsgLogMapper;
	
	@Resource
	private ISystemService systemService;
	
	private Map<String, MachineInfo> machineInfoMap = new HashMap<String, MachineInfo>();
	
	@Override
	public ResultForDeliveryClientLoginLog dologin(DeliveryExamineeInfo examineeInfo, HttpServletRequest request) {
		
		Map<String, Object> params = new HashMap<String, Object>();
		
		params.put("uniquecode", uniquecode);	
		
		String ip = getAddrIp(request);
		
		try {
			
			Result testConn = systemService.TestConn();
			
			if (testConn.getCode() == 200) {
				if (examineeInfo.getsNo() != null && !"".equals(examineeInfo.getsNo())) {
					params.put("sNo", examineeInfo.getsNo());
				}
				
				if (examineeInfo.geteNo() != null && !"".equals(examineeInfo.geteNo())) {
					params.put("eNo", examineeInfo.geteNo());
				}
				
				if (examineeInfo.getField1() != null && !"".equals(examineeInfo.getField1())) {
					params.put("field1", examineeInfo.getField1());
				}
				
				String resultStr = HttpClientUtil.doPost(centerUrl + centerClientLoginUrl, params);
				
				GsonBuilder builder = new GsonBuilder();
				    
				builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() { 
					@Override   
					public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
						return new Date(json.getAsJsonPrimitive().getAsLong()); 
					}
				});
				
				ResultForDeliveryClientLoginLogs result = builder.create().fromJson(resultStr, ResultForDeliveryClientLoginLogs.class);
				
				if ("200".equals(result.getStatusCode())) {
					List<DeliveryClientLoginLog> datas = result.getData();
					
					int idx = -1;  // 最终取哪场考试
					Long minStartTime = 0L; // 大于当前时间的最小开始时间
					for (int i = 0; i < datas.size(); i++) {
						DeliveryClientLoginLog log = datas.get(i);
						
						Long now = log.getServerTime().getTime();
						Long startTime = log.getDeliveryExamInfo().geteStarttime().getTime();
						Long endTime = log.getDeliveryExamInfo().geteEndtime().getTime();
						Long endTimeDelay = endTime;
						
						// 查询该考生是否已经参加过考试
						DeliveryCommitLog commitlog = new DeliveryCommitLog();
						// 查询该考生是否被延时交卷
						DeliverySocketMsgLog msgLog = new DeliverySocketMsgLog();
						
						commitlog.setsNo(log.getsNo());
						msgLog.setsNo(log.getsNo());
						
						commitlog.seteNo(log.geteNo());
						msgLog.seteNo(log.geteNo());

						commitlog.setsName(log.getField1());
						msgLog.setsName(log.getField1());
						
						commitlog.seteId(log.geteId());
						msgLog.seteId(log.geteId());
						
						List<DeliveryCommitLog> commitLogs = deliveryCommitLogMapper.selectByParams(commitlog);
						
						if (commitLogs.size() > 0) {
							
							continue;
							// return new ResultForDeliveryClientLoginLog("8106", "该考生已参加过考试");
						}
						
						List<DeliverySocketMsgLog> msgLogs = deliverySocketMsgLogMapper.selectByParams(msgLog);
						
						if (msgLogs.size() > 0) {
							msgLog = msgLogs.get(0);
						}
						
						if (msgLog.getMsgType() != null && msgLog.getMsgType() == 1) {
							log.setDelayTime(msgLog.getDelayTime());
							endTimeDelay += (msgLog.getDelayTime() == null ? 0L :msgLog.getDelayTime().longValue()) ; 
						}
						
						List<DeliveryClientLoginLog> loginLog = deliveryClientLoginLogMapper.selectByParams(log);
						
						if(loginLog.size() > 0) {
							log.setIsFirstLogin(0);
						} else {
							log.setIsFirstLogin(1);
						}
						
						if (now > endTimeDelay) {
							continue;
						}
						
						if (now > startTime && now <= endTimeDelay) {
							idx = i;
							break;
						}
						
						if (now <= startTime) {
							if (i == 0) {
								minStartTime = startTime;
								idx = 0;
							} else {
								if (minStartTime == 0) {
									minStartTime = startTime;
									idx = i;
								}
								if (startTime < minStartTime) {
									minStartTime = startTime;
									idx = i;
								}
							}
						}
					}
					if (idx == -1) {
						
						return new ResultForDeliveryClientLoginLog("8106", "该考生无此考号的考试，请核对登录信息");
					} else {
						DeliveryClientLoginLog returnLog = datas.get(idx);
						returnLog.setId(Tool.getUUID());
						returnLog.setCreateTime(new Date());
						deliveryClientLoginLogMapper.insert(returnLog);
						if (machineInfoMap.get(ip) != null) {
							MachineInfo info = machineInfoMap.get(ip);
							info.setField1(returnLog.getqId());
							info.setField4(returnLog.geteId());
							info.setsNo(returnLog.getsNo());
							info.seteNo(returnLog.geteNo());
							info.setsName(returnLog.getField1());
							info.setStatus(0);
							machineInfoMap.put(ip, info);
						} else {
							MachineInfo info = new MachineInfo();
							info.setField1(returnLog.getqId());
							info.setField4(returnLog.geteId());
							info.setIp(ip);
							String ipStr = ip.replaceAll( "(\\d+)", "00$1" );
							ipStr = ipStr.replaceAll( "0*(\\d{3})", "$1" );
							info.setField3(ipStr);
							info.setsNo(returnLog.getsNo());
							info.seteNo(returnLog.geteNo());
							info.setsName(returnLog.getField1());
							info.setStatus(0);
							machineInfoMap.put(ip, info);
						}
						
						ResultForDeliveryClientLoginLog res = new ResultForDeliveryClientLoginLog();
						
						res.setStatusCode("200");
						res.setSuccess(true);
						res.setMessage("登录成功");
						res.setData(returnLog);
						
						return res;
						
					}
				} else {
					
					return new ResultForDeliveryClientLoginLog(result.getStatusCode(), result.getMessage());
				}
				
/*				if ("200".equals(result.getStatusCode())) {
					result.getData().setId(Tool.getUUID());
					result.getData().setCreateTime(new Date());
					List<DeliveryClientLoginLog> logs = deliveryClientLoginLogMapper.selectByParams(result.getData());
					
					if(logs.size() > 0) {
						result.getData().setIsFirstLogin(0);
					} else {
						result.getData().setIsFirstLogin(1);
					}
					
					if (msgLog.getMsgType() != null && msgLog.getMsgType() == 1) {
						result.getData().setDelayTime(msgLog.getDelayTime());
					}
					
					deliveryClientLoginLogMapper.insert(result.getData());
					
					if (machineInfoMap.get(ip) != null) {
						MachineInfo info = machineInfoMap.get(ip);
						info.setField1(result.getData().getqId());
						info.setField4(result.getData().geteId());
						info.setsNo(result.getData().getsNo());
						info.seteNo(result.getData().geteNo());
						info.setsName(result.getData().getField1());
						info.setStatus(0);
						machineInfoMap.put(ip, info);
					} else {
						MachineInfo info = new MachineInfo();
						info.setField1(result.getData().getqId());
						info.setField4(result.getData().geteId());
						info.setIp(ip);
						String ipStr = ip.replaceAll( "(\\d+)", "00$1" );
						ipStr = ipStr.replaceAll( "0*(\\d{3})", "$1" );
						info.setField3(ipStr);
						info.setsNo(result.getData().getsNo());
						info.seteNo(result.getData().geteNo());
						info.setsName(result.getData().getField1());
						info.setStatus(0);
						machineInfoMap.put(ip, info);
					}
					
					return result;
				} else {
					
					return result;
				}*/
			} else {
				
				List<DeliveryExamineeInfo> examinees =  deliveryExamineeInfoMapper.selectByParams(examineeInfo);
				ResultForDeliveryClientLoginLog result = new ResultForDeliveryClientLoginLog();
				
				if (examinees.size() > 0) {
					
					int idx = -1;  // 最终取哪场考试
					Long minStartTime = 0L; // 大于当前时间的最小开始时间
					List<DeliveryClientLoginLog> datas = new ArrayList<DeliveryClientLoginLog>();
					DeliveryClientLoginLog log = null;
					for (int i = 0; i < examinees.size(); i++) {
						log = new DeliveryClientLoginLog();
						Integer eId = examinees.get(i).geteId();
						DeliveryExamInfo examInfo = deliveryExamInfoMapper.selectByPrimaryKey(eId);
						String paperUrl = "";
						if (examInfo != null) {
							String qId =examinees.get(i).getField2(); // Tool.getRandomBankId(qIds);
							DeliveryQuestionBank bank = deliveryQuestionBankMapper.selectByPrimaryKey(qId);
						
							if (bank != null) {
								paperUrl = "/" + eId + "/" + qId;
							}
							log.setId(Tool.getUUID());
							log.seteId(eId);
							log.setqId(qId);
							log.setPaperUrl(paperUrl);
							log.setsNo(examinees.get(i).getsNo());
							log.seteNo(examinees.get(i).geteNo());
							log.setField1(examinees.get(i).getField1());
							log.setCreateTime(new Date());
							log.setDeliveryExamInfo(examInfo);
							datas.add(log);
							
							Long now = new Date().getTime();
							Long startTime = examInfo.geteStarttime().getTime();
							Long endTime = examInfo.geteEndtime().getTime();
							Long endTimeDelay = endTime;
							
							// 查询该考生是否已经参加过考试
							DeliveryCommitLog commitlog = new DeliveryCommitLog();
							// 查询该考生是否被延时交卷
							DeliverySocketMsgLog msgLog = new DeliverySocketMsgLog();
							
							commitlog.setsNo(examinees.get(i).getsNo());
							msgLog.setsNo(examinees.get(i).getsNo());
							
							commitlog.seteNo(examinees.get(i).geteNo());
							msgLog.seteNo(examinees.get(i).geteNo());

							commitlog.setsName(examinees.get(i).getField1());
							msgLog.setsName(examinees.get(i).getField1());
							
							commitlog.seteId(examinees.get(i).geteId());
							msgLog.seteId(examinees.get(i).geteId());
							
							List<DeliveryCommitLog> commitLogs = deliveryCommitLogMapper.selectByParams(commitlog);
							
							if (commitLogs.size() > 0) {
								
								continue;
								// return new ResultForDeliveryClientLoginLog("8106", "该考生已参加过考试");
							}
							
							List<DeliverySocketMsgLog> msgLogs = deliverySocketMsgLogMapper.selectByParams(msgLog);
							
							if (msgLogs.size() > 0) {
								msgLog = msgLogs.get(0);
							}
							
							if (msgLog.getMsgType() != null && msgLog.getMsgType() == 1) {
								log.setDelayTime(msgLog.getDelayTime());
								endTimeDelay += (msgLog.getDelayTime() == null ? 0L :msgLog.getDelayTime().longValue()) ; 
							}
							
							List<DeliveryClientLoginLog> loginLog = deliveryClientLoginLogMapper.selectByParams(log);
							
							if(loginLog.size() > 0) {
								log.setIsFirstLogin(0);
							} else {
								log.setIsFirstLogin(1);
							}
							
							if (now > endTimeDelay) {
								continue;
							}
							
							if (now > startTime && now <= endTimeDelay) {
								idx = i;
								break;
							}
							
							if (now <= startTime) {
								if (i == 0) {
									minStartTime = startTime;
									idx = i;
								} else {
									if (minStartTime == 0) {
										minStartTime = startTime;
										idx = i;
									}
									if (startTime < minStartTime) {
										minStartTime = startTime;
										idx = i;
									}
								}
							}
						}
						
					}
					
					if (idx == -1) {
						
						return new ResultForDeliveryClientLoginLog("8106", "该考生无此考号的考试，请核对登录信息");
					} else {
						DeliveryClientLoginLog returnLog = datas.get(idx);
						returnLog.setId(Tool.getUUID());
						returnLog.setCreateTime(new Date());
						deliveryClientLoginLogMapper.insert(returnLog);
						if (machineInfoMap.get(ip) != null) {
							MachineInfo info = machineInfoMap.get(ip);
							info.setField1(returnLog.getqId());
							info.setField4(returnLog.geteId());
							info.setsNo(returnLog.getsNo());
							info.seteNo(returnLog.geteNo());
							info.setsName(returnLog.getField1());
							info.setStatus(0);
							machineInfoMap.put(ip, info);
						} else {
							MachineInfo info = new MachineInfo();
							info.setField1(returnLog.getqId());
							info.setField4(returnLog.geteId());
							info.setIp(ip);
							String ipStr = ip.replaceAll( "(\\d+)", "00$1" );
							ipStr = ipStr.replaceAll( "0*(\\d{3})", "$1" );
							info.setField3(ipStr);
							info.setsNo(returnLog.getsNo());
							info.seteNo(returnLog.geteNo());
							info.setsName(returnLog.getField1());
							info.setStatus(0);
							machineInfoMap.put(ip, info);
						}
						
						ResultForDeliveryClientLoginLog res = new ResultForDeliveryClientLoginLog();
						
						res.setStatusCode("200");
						res.setSuccess(true);
						res.setMessage("登录成功");
						res.setData(returnLog);
						
						return res;
					}
					
/*					DeliveryClientLoginLog log = new DeliveryClientLoginLog();
					Integer eId = examinees.get(0).geteId();
					DeliveryExamInfo examInfo = deliveryExamInfoMapper.selectByPrimaryKey(eId);
					String paperUrl = "";
					if (examInfo != null) {
						// String qIds = examInfo.getqId();
						
						String qId =examinees.get(0).getField2(); // Tool.getRandomBankId(qIds);
						
						DeliveryQuestionBank bank = deliveryQuestionBankMapper.selectByPrimaryKey(qId);
						
						if (bank != null) {
							paperUrl = "/" + eId + "/" + qId;
						}
						log.setId(Tool.getUUID());
						log.seteId(eId);
						log.setqId(qId);
						log.setPaperUrl(paperUrl);
						if (examineeInfo.getsNo() != null && !"".equals(examineeInfo.getsNo())) {
							log.setsNo(examineeInfo.getsNo());
						}
						
						if (examineeInfo.geteNo() != null && !"".equals(examineeInfo.geteNo())) {
							log.seteNo(examineeInfo.geteNo());
						}
						
						if (examineeInfo.getField1() != null && !"".equals(examineeInfo.getField1())) {
							log.setField1(examineeInfo.getField1());
						}
						
						log.setCreateTime(new Date());
						
						List<DeliveryClientLoginLog> logs = deliveryClientLoginLogMapper.selectByParams(log);
						
						if(logs.size() > 0) {
							log.setIsFirstLogin(0);
						} else {
							log.setIsFirstLogin(1);
						}
						
						if (msgLog.getMsgType() != null && msgLog.getMsgType() == 1) {
							result.getData().setDelayTime(msgLog.getDelayTime());
						}
						
						log.setServerTime(new Date());
						deliveryClientLoginLogMapper.insert(log);
						
						log.setDeliveryExamInfo(examInfo);
						result.setStatusCode("200");
						result.setSuccess(true);
						result.setMessage("登录成功");
						result.setData(log);
						
						if (machineInfoMap.get(ip) != null) {
							MachineInfo info = machineInfoMap.get(ip);
							info.setField1(result.getData().getqId());
							info.setField4(result.getData().geteId());
							info.setsNo(result.getData().getsNo());
							info.seteNo(result.getData().geteNo());
							info.setsName(result.getData().getField1());
							info.setStatus(0);
							machineInfoMap.put(ip, info);
						} else {
							MachineInfo info = new MachineInfo();
							info.setField1(result.getData().getqId());
							info.setField4(result.getData().geteId());
							info.setsNo(result.getData().getsNo());
							info.seteNo(result.getData().geteNo());
							info.setsName(result.getData().getField1());
							info.setIp(ip);
							String ipStr = ip.replaceAll( "(\\d+)", "00$1" );
							ipStr = ipStr.replaceAll( "0*(\\d{3})", "$1" );
							info.setField3(ipStr);
							info.setStatus(0);
							machineInfoMap.put(ip, info);
						}
						
						return result;
					} else {
					
					}*/
				} else {
					result.setStatusCode("8106");
					result.setSuccess(false);
					result.setMessage("登录失败，请仔细核对登录信息");
					
					return result;
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return null;
	}

	private String getAddrIp(HttpServletRequest request) {
		String ipString = request.getHeader("x-forwarded-for");
		if (StringUtils.isBlank(ipString)
				|| "unknown".equalsIgnoreCase(ipString)) {
			ipString = request.getHeader("Proxy-Client-IP");
		}
		if (StringUtils.isBlank(ipString)
				|| "unknown".equalsIgnoreCase(ipString)) {
			ipString = request.getHeader("WL-Proxy-Client-IP");
		}
		if (StringUtils.isBlank(ipString)
				|| "unknown".equalsIgnoreCase(ipString)) {
			ipString = request.getRemoteAddr();
		}

		// 多个路由时，取第一个非unknown的ip
		final String[] arr = ipString.split(",");
		for (final String str : arr) {
			if (!"unknown".equalsIgnoreCase(str)) {
				ipString = str;
				break;
			}
		}

		return ipString;
	}

	public Map<String, MachineInfo> getMachineInfoMap() {
		return machineInfoMap;
	}

	public void setMachineInfoMap(Map<String, MachineInfo> machineInfoMap) {
		this.machineInfoMap = machineInfoMap;
	}
}
